package top.wshape1.rpc.starter;

import lombok.Data;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import redis.clients.jedis.Jedis;
import top.wshape1.rpc.config.ConsumerConfig;
import top.wshape1.rpc.config.JJRpcConfig;
import top.wshape1.rpc.config.RegistryConfig;

import java.util.List;


/**
 * @author Wshape1
 * @version 1.0
 * @description JJRpcProperties
 * @since 2024-02-21
 */

@ConfigurationProperties(prefix = "jjrpc")
@Data
public class JJRpcProperties implements InitializingBean {

    /**
     * 消费者配置
     */
    private ConsumerProperties consumer;

    /**
     * 生产者/消费者的IP
     */
    private String host = "127.0.0.1";

    /**
     * 消费者/生产者的端口
     */
    private int port;

    /**
     * 生产者验证请求和消费者发送的令牌
     */
    private String token = "9536CD46F8C037120076887C54176029";

    private RegistryProperties registry;

    private CompressProperties compress;

    @Override
    public void afterPropertiesSet() {
        System.out.println("jjrpc配置初始化完成===========================================================================================================================================================");
        JJRpcConfig config = JJRpcConfig.CONFIG;
        config.setHost(host);
        config.setPort(port);
        config.setToken(token);

        if (consumer != null) {
            ConsumerConfig consumerConfig = config.getConsumer();
            consumerConfig.setCallTimeout(consumer.callTimeout);
        }

        if (compress != null)
            config.getCompress().setEnabled(compress.isEnabled());

        if (registry != null) {
            RegistryConfig registryConfig = config.getRegistry();
            if (registry.redis != null) {
                RegistryConfig.RedisRegistryConfig redisRegistryConfig = getRedisRegistryConfig();
                registryConfig.setRedis(redisRegistryConfig);
            }
            if (registry.zookeeper != null) {
                RegistryConfig.ZookeeperRegistryConfig zkRegistryConfig = getZookeeperRegistryConfig();
                registryConfig.setZookeeper(zkRegistryConfig);
            }
            if (registry.nacos != null) {
                RegistryConfig.NacosRegistryConfig nacosRegistryConfig = getNacosRegistryConfig();
                registryConfig.setNacos(nacosRegistryConfig);
            }
        }

    }

    private RegistryConfig.NacosRegistryConfig getNacosRegistryConfig() {
        RegistryConfig.NacosRegistryConfig nacosRegistryConfig = new RegistryConfig.NacosRegistryConfig();
        nacosRegistryConfig.setAddress(registry.nacos.address);
        nacosRegistryConfig.setGroup(registry.nacos.group);
        nacosRegistryConfig.setEnableNacosLoadBalance(registry.nacos.enableNacosLoadBalance);
        return nacosRegistryConfig;
    }

    private RegistryConfig.ZookeeperRegistryConfig getZookeeperRegistryConfig() {
        RegistryConfig.ZookeeperRegistryConfig zkRegistryConfig = new RegistryConfig.ZookeeperRegistryConfig(registry.zookeeper.address);
        zkRegistryConfig.setConnectionTimeout(registry.zookeeper.connectionTimeout);
        zkRegistryConfig.setSessionTimeout(registry.zookeeper.sessionTimeout);
        zkRegistryConfig.setAcl(registry.zookeeper.acl);
        zkRegistryConfig.setRootNode(registry.zookeeper.rootNode);
        return zkRegistryConfig;
    }

    private RegistryConfig.RedisRegistryConfig getRedisRegistryConfig() {
        RegistryConfig.RedisRegistryConfig redisRegistryConfig = new RegistryConfig.RedisRegistryConfig(registry.redis.host, registry.redis.port);
        redisRegistryConfig.setDb(registry.redis.db);
        redisRegistryConfig.setUsername(registry.redis.username);
        redisRegistryConfig.setPassword(registry.redis.password);
        GenericObjectPoolConfig<Jedis> poolConfig = new GenericObjectPoolConfig<>();
        poolConfig.setMaxIdle(registry.redis.maxIdle);
        poolConfig.setMaxTotal(registry.redis.maxTotal);
        poolConfig.setMinIdle(registry.redis.minIdle);
        redisRegistryConfig.setPool(poolConfig);
        redisRegistryConfig.setSsl(registry.redis.ssl);
        redisRegistryConfig.setPrefix(registry.redis.prefix);
        redisRegistryConfig.setConnectionTimeout(registry.redis.connectionTimeout);
        redisRegistryConfig.setSoTimeout(registry.redis.soTimeout);
        return redisRegistryConfig;
    }

    @Data
    private static class CompressProperties {
        /**
         * 是否开启数据压缩
         */
        private boolean enabled = false;
    }

    @Data
    private static class ConsumerProperties {
        /**
         * 调用远程服务超时时间 单位ms
         */
        private int callTimeout = 3000;

        /**
         * 容错机制 重试次数
         */
        private int retryTimes = 3;

        /**
         * 容错机制 重试间隔 单位ms
         */
        private int retryInterval = 1000;
    }

    @Data
    private static class RegistryProperties {

        private RedisRegistryProperties redis;

        private ZookeeperRegistryProperties zookeeper;

        private NacosRegistryProperties nacos;

        @Data
        private static class RedisRegistryProperties {

            private String host = "localhost";
            private int port = 6379;
            private String username;
            private String password;
            private int db = 0;
            /**
             * 在redis中存储的Key的前缀
             */
            private String prefix = "jjrpc";
            /**
             * 连接超时时间 默认2000ms
             */
            private int connectionTimeout = 2000;

            /**
             * 读取超时时间 默认3000ms
             */
            private int soTimeout = 3000;

            private boolean ssl = false;

            /**
             * 连接池最大连接数 默认8
             */
            private int maxTotal = 8;

            /**
             * 连接池最大空闲连接数 默认8
             */
            private int maxIdle = 8;

            /**
             * 连接池最小空闲连接数 默认0
             */
            private int minIdle = 0;

        }

        @Data
        private static class ZookeeperRegistryProperties {
            /**
             * connectString: 'ip:port' or 'ip1:port1,ip2:port2,...'
             */
            private String address = "localhost:2181";
            private String rootNode = "jjrpc";
            /**
             * ACL: List of 'scheme:id:perm'
             */
            private List<String> acl;
            /**
             * 会话超时 单位ms
             */
            private int sessionTimeout = 3000;
            /**
             * 连接超时 单位ms
             */
            private int connectionTimeout = 2000;
        }

        @Data
        private static class NacosRegistryProperties {
            private String address = "localhost:8848";
            private String group = "JJRPC";
            /**
             * 是否启用Nacos负载均衡，启用后服务发现只会返回一个服务实例，JJRPC提供的负载均衡和部分容错机制将失效
             */
            private boolean enableNacosLoadBalance = false;
        }
    }

}
